-module( octree_test ).
-export( [run/0] ).

-define( STEP, 40 ).

run() ->
  smoke(),
  spawn( fun() -> testArcanoid( point ) end ),
  timer:sleep( 1000 ), %To fix some strange WX deadlock
  spawn( fun() -> testArcanoid( box ) end ),
  receive after infinity -> ok end,
  init:stop().



smoke() ->
  B = { { -50.0, -100.0, -100.0 }, { 350.0, 300.0, 100.0 } },
  CS = { 100, 100, 100 },
  F = fun( CellBounds, Aux ) -> { { cell, Aux, CellBounds }, Aux + 1 } end,
  { T, Aux } = octree:build( B, CS, F, 0 ),
  io:format( "Tree built:\n~p\n~p nodes\n", [T, Aux] ),
  WP = octree:walkPoint( T, { 0.0, 0.0, 0.0 }, fun( V ) -> V end ),
  io:format( "Walk point: ~p\n", [WP] ),
  true.
  
  
testArcanoid( Type ) ->
  B = { { -50.0, -100.0, -10.0 }, { 350.0, 300.0, 10.0 } },
  CS = { 50.0, 50.0, 20.0 },
  F = fun( CellBounds, Aux ) -> { { cell, Aux, CellBounds }, Aux + 1 } end,
  { T, _Aux } = octree:build( B, CS, F, 0 ),
  B2 = { -50.0, -100.0, +350.0, +300.0 },
  Vis = vis:start( B2 ),
  case Type of
    point -> arcanoidLoop( T, B2, {150.0, 100.0}, {92.0, -76.0}, Vis );
    box -> boxArcanoidLoop( T, B2, {100.0, 100.0}, {80.0, 80.0}, {45.0, 35.0}, Vis )
  end.


arcanoidLoop( T, {MINX, MINY, MAXX, MAXY}, {X, Y}, {VX, VY}, Vis ) ->
  timer:sleep( ?STEP ),
  XX = X + ?STEP / 1000.0 * VX,
  YY = Y + ?STEP / 1000.0 * VY,
  { NX, NewVX } = if
    ( XX < MINX ) -> { MINX, +abs( VX ) };
    ( XX > MAXX ) -> { MAXX, -abs( VX ) };
    true -> { XX, VX }
  end,
  { NY, NewVY } = if
    ( YY < MINY ) -> { MINY, +abs( VY ) };
    ( YY > MAXY ) -> { MAXY, -abs( VY ) };
    true -> { YY, VY }
  end,

  vis:remove( Vis, arcanoid ),
  vis:addDiamond( Vis, NX, NY, 10.0, [ {tag1, arcanoid}, {color, red} ] ),
  
  F = fun( { cell, Idx, Bounds } ) -> { Idx, Bounds } end,
  { Idx, Box } = octree:walkPoint( T, { NX, NY, 0.0 }, F ),
  { {BoxX0, BoxY0, _BoxZ0}, {BoxX1, BoxY1, _BoxZ1} } = Box,
  vis:addRect( Vis, BoxX0, BoxY0, BoxX1, BoxY1, [ {tag1, arcanoid}, {color, blue} ] ),
  {CX, CY, _} = geom:boxCenter( Box ),
  vis:addText( Vis, CX, CY, integer_to_list( Idx ), [ {tag1, arcanoid}, {color, white} ] ),

  arcanoidLoop( T, {MINX, MINY, MAXX, MAXY}, {NX, NY}, {NewVX, NewVY}, Vis ).
  
  
  
boxArcanoidLoop( T, {MINX, MINY, MAXX, MAXY}, {X, Y}, {SX, SY}, {VX, VY}, Vis ) ->
  timer:sleep( ?STEP ),
  XX = X + ?STEP / 1000.0 * VX,
  YY = Y + ?STEP / 1000.0 * VY,
  { NX, NewVX } = if
    ( XX < MINX ) -> { MINX, +abs( VX ) };
    ( ( XX + SX ) > MAXX ) -> { MAXX - SX, -abs( VX ) };
    true -> { XX, VX }
  end,
  { NY, NewVY } = if
    ( YY < MINY ) -> { MINY, +abs( VY ) };
    ( ( YY + SY ) > MAXY ) -> { MAXY - SY, -abs( VY ) };
    true -> { YY, VY }
  end,

  vis:remove( Vis, arcanoid ),
  vis:addRect( Vis, NX, NY, NX + SX, NY + SY, [ {tag1, arcanoid}, {color, red} ] ),
  
  F = fun( { cell, Idx, Box={ {BoxX0, BoxY0, _BoxZ0}, {BoxX1, BoxY1, _BoxZ1} } }, A ) ->
    vis:addRect( Vis, BoxX0, BoxY0, BoxX1, BoxY1, [ {tag1, arcanoid}, {color, blue} ] ),
    {CX, CY, _} = geom:boxCenter( Box ),
    vis:addText( Vis, CX, CY, integer_to_list( Idx ), [ {tag1, arcanoid}, {color, white} ] ),
    A
  end,
  B = { { NX, NY, -100.0 }, { NX + SX, NY + SY, 100.0 } },
  octree:walkBox( T, B, F, null ),

  boxArcanoidLoop( T, {MINX, MINY, MAXX, MAXY}, {NX, NY}, {SX, SY}, {NewVX, NewVY}, Vis ).
